﻿#region License
// (c) Intergen.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using TextGlow.Control.Utilities;

namespace TextGlow.Control.UI
{
  public partial class Container : UserControl
  {
    private readonly IList<FrameworkElement> _pages; 
    private int _selectedIndex;

    public event EventHandler SaveButtonClick
    {
      add { Header.SaveButtonClick += value; }
      remove { Header.SaveButtonClick -= value; }
    }

    public event EventHandler FullScreenButtonClick
    {
      add { Header.FullScreenButtonClick += value; }
      remove { Header.FullScreenButtonClick -= value; }
    }

    public event EventHandler PreviousPageButtonClick
    {
      add { Header.PreviousPageButtonClick += value; }
      remove { Header.PreviousPageButtonClick -= value; }
    }

    public event EventHandler NextPageButtonClick
    {
      add { Header.NextPageButtonClick += value; }
      remove { Header.NextPageButtonClick -= value; }
    }

    public int CurrentPageIndex
    {
      get { return _selectedIndex; }
    }

    public int PageCount
    {
      get { return PageContainer.Children.Count; }
    }

    public event EventHandler CoverClick;
    public event EventHandler ProgressHidden;
    
    public Container()
    {
      InitializeComponent();

      PageContainer.Opacity = 0;

      _pages = new List<FrameworkElement>();
      FadeProgressPanel.Completed += new EventHandler(FadeProgressPanel_Completed);
    }

    protected override Size ArrangeOverride(Size finalSize)
    {
      LayoutRoot.Arrange(LayoutUtils.CreateRect(LayoutUtils.Zero, finalSize));

      Rect headerBounds = new Rect(5, 5, finalSize.Width - 10, finalSize.Height - 5);
      Header.SetBounds(headerBounds);

      Rect footerBounds = new Rect(0, finalSize.Height - 100, finalSize.Width, 100);
      Footer.SetBounds(footerBounds);

      Rect pageContainerBounds = new Rect(0, 0, finalSize.Width, finalSize.Height);
      PageContainer.SetBounds(pageContainerBounds);

      ProgressPanel.SetLocation(new Point((Width - ProgressPanel.Width) / 2, (Height - ProgressPanel.Height) / 2));

      ProgressText.SetLocation(new Point((ProgressPanel.Width - ProgressText.ActualWidth) / 2, 0));

      for (int i = 0; i < PageContainer.Children.Count; i++)
      {
        PageCover cover = (PageCover)PageContainer.Children[i];
        Point position = CalculateCoverPosition(i, _selectedIndex);

        cover.SetTranslation(position);
      }

      return finalSize;
    }

    private void FadeProgressPanel_Completed(object sender, EventArgs e)
    {
      EventHandler progressHidden = ProgressHidden;
      if (progressHidden != null)
        progressHidden(sender, e);
    }

    public void SetDocumentUriText(Uri documentUri)
    {
      Header.SetDocumentUriText(documentUri);
    }

    public void SetProgress(double progressPercentage)
    {
      ProgressBar.Width = progressPercentage * 2;
    }

    public void AddPage(FrameworkElement page)
    {
      _pages.Add(page);

      PageCover cover = new PageCover();

      cover.Height = 595;
      cover.Width = cover.Height / 1.4142449010256197707152286276925;
      cover.Container.Children.Add(page);

      cover.SetName("Cover_" + PageContainer.Children.Count);

      cover.Click += new EventHandler(cover_Click);

      cover.HorizontalAlignment = HorizontalAlignment.Center;
      cover.VerticalAlignment = VerticalAlignment.Center;

      PageContainer.Children.Add(cover);

      cover.UpdateLayout();
    }

    private void cover_Click(object sender, EventArgs e)
    {
      EventHandler coverClick = CoverClick;
      if (coverClick != null)
        coverClick(sender, e);
    }

    private Point CalculateCoverPosition(int index, int selectedIndex)
    {
      PageCover cover1 = (PageCover)PageContainer.Children[index];
      double coverwidth = cover1.Width;
      double horizontalCenter = (PageContainer.Width - coverwidth) / 2;
      double verticalCenter = (PageContainer.Height - cover1.Height) / 2;
      double backgroundScaledWidth = coverwidth * 0.8;
      double perspectivebotton = 10;

      int currentFromIndex = Math.Abs(index - selectedIndex);

      Point position = new Point();
      if (index == selectedIndex)
      {
        position.X = horizontalCenter;
        position.Y = verticalCenter;
      }
      else if (index < selectedIndex)
      {
        position.X = horizontalCenter - (coverwidth * (currentFromIndex));
        position.Y = verticalCenter;
      }
      else
      {
        position.X = horizontalCenter + (coverwidth * currentFromIndex) + (coverwidth - backgroundScaledWidth);
        position.Y = verticalCenter - (Math.Tan(perspectivebotton * (Math.PI / 180)) * backgroundScaledWidth);
      }

      return position;
    }

    public void SelectCover(int selectedIndex)
    {
        string headerText = string.Format("{0}/{1}", selectedIndex + 1, PageCount);
        Header.SetPageText(headerText);

        _selectedIndex = selectedIndex;

        if (PageContainer.Children.Count == 0)

            return;

        PageCover cover1 = (PageCover) PageContainer.Children[selectedIndex];


        // Setup
        double coverwidth = cover1.Width;
        double halfCoverWidth = coverwidth/2;
        double center = (PageContainer.Width - coverwidth)/2;

        double perspectivetop = 60;
        double perspectivebotton = 10;
        double scaley = 0.8;
        double scalex = scaley*(1.0 - perspectivetop/coverwidth);
        double backgroundScaledWidth = coverwidth*0.8;

        // Layout
        for (var i = 0; i < PageContainer.Children.Count; i++)
        {
            PageCover cover = (PageCover) PageContainer.Children[i];

            if (i - 2 > _selectedIndex || i + 2 < _selectedIndex)
            {
                cover.Visibility = Visibility.Collapsed;
                //continue;
            }
            else
            {
                cover.Visibility = Visibility.Visible;
            }

            FrameworkElement coverContents = (FrameworkElement) cover.Canvas.FindName("video0");

            int zIndex;
            double scaleX;
            double scaleY;
            double angleX;
            double opacity;
            Cursor cursor;

            int currentFromIndex = Math.Abs(i - selectedIndex);

            if (i < selectedIndex)
            {
                zIndex = i;

                scaleX = scalex;
                scaleY = scaley;
                angleX = -perspectivebotton;
                opacity = 0.6;
                cursor = Cursors.Hand;
            }
            else if (i > selectedIndex)
            {
                var ii = (i - selectedIndex - 1);
                zIndex = (PageContainer.Children.Count - 1) - ii;

                scaleX = scalex;
                scaleY = scaley;
                angleX = perspectivebotton;
                opacity = 0.6;
                cursor = Cursors.Hand;
            }
            else
            {
                zIndex = PageContainer.Children.Count;

                scaleX = 1;
                scaleY = 1;
                angleX = 0;
                opacity = 1;
                cursor = Cursors.Arrow;
            }

            coverContents.Cursor = cursor;

            Point position = CalculateCoverPosition(i, selectedIndex);

            Storyboard sb = (Storyboard) cover.Animation;
            ((DoubleAnimation) sb.Children[0]).To = scaleX;
            ((DoubleAnimation) sb.Children[1]).To = scaleY;
            ((DoubleAnimation) sb.Children[2]).To = angleX;
            ((DoubleAnimation) sb.Children[3]).To = position.X;
            ((DoubleAnimation) sb.Children[4]).To = position.Y;
            ((DoubleAnimation) sb.Children[5]).To = opacity;

            cover.SetValue(Canvas.ZIndexProperty, zIndex);

            sb.Begin();
        }
    }

    public void ShowProgressPanel()
    {
      ProgressPanel.Visibility = Visibility.Visible;
      ProgressPanel.Opacity = 1;
    }

    public void HideProgressPanel()
    {
      FadeProgressPanel.Begin();
    }

    public void SetProgressLabel(string s)
    {
      ProgressText.Text = s;

      InvalidateArrange();
    }

    public void ClearPages()
    {
      _pages.Clear();
      PageContainer.Children.Clear();
      PageContainer.Opacity = 0;
    }

    public void ShowPages()
    {
      ProgressPanel.Visibility = Visibility.Collapsed;

      _selectedIndex = 0;

      SelectCover(_selectedIndex);

      PageContainer.Opacity = 1;
    }
  }
}
